package xin.marcher.module.diplomacy.api.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import xin.marcher.module.common.constants.diplomacy.AbstractRedisKeyConstants;
import xin.marcher.module.common.core.JsonResult;
import xin.marcher.module.common.exception.ProductErrorCodeEnum;
import xin.marcher.module.common.utils.JsonUtil;
import xin.marcher.module.common.utils.ParamCheckUtil;
import xin.marcher.module.diplomacy.api.ProductCompensateApi;
import xin.marcher.module.diplomacy.domain.dto.ProductCompensateCollectDTO;
import xin.marcher.module.diplomacy.domain.dto.ProductCompensateRelationDTO;
import xin.marcher.module.diplomacy.domain.entity.ProductDetailDO;
import xin.marcher.module.diplomacy.domain.query.ProductCompensateQuery;
import xin.marcher.module.diplomacy.domain.query.ProductCompensateRelationQuery;
import xin.marcher.module.diplomacy.manager.custom.cache.SkuSellerCache;

import javax.annotation.Resource;
import java.util.*;

import static xin.marcher.module.common.constants.diplomacy.BaseConstants.PAGE_NO_1;
import static xin.marcher.module.common.constants.diplomacy.BaseConstants.PAGE_SIZE_1000;

/**
 * 商品可补服务
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = ProductCompensateApi.class, retries = 0)
public class ProductCompensateApiImpl implements ProductCompensateApi {

    @Resource
    private SkuSellerCache skuSellerCache;

    /**
     * 分页查询可补商品
     *
     * @param productCompensateQuery
     * @return
     */
    @Override
    public JsonResult<ProductCompensateCollectDTO> getCompensateSkuByPage(ProductCompensateQuery productCompensateQuery) {
        checkCompensateSkuByPageParams(productCompensateQuery);

        int pageNo = PAGE_NO_1;
        int pageSize = PAGE_SIZE_1000;
        if (Objects.nonNull(productCompensateQuery.getPageNo())) {
            pageNo = productCompensateQuery.getPageNo();
        }
        if (Objects.nonNull(productCompensateQuery.getPageSize())) {
            pageSize = productCompensateQuery.getPageSize();
        }
        int offset = (pageNo - 1) * pageSize;

        String redisKey = AbstractRedisKeyConstants.getSellerTypeCompensateSkuZsetKey(productCompensateQuery.getSellerId());
        Optional<List<String>> optional = skuSellerCache.listRedisSortedSetData(productCompensateQuery.getSellerId(),
                offset, pageSize, AbstractRedisKeyConstants::getSellerTypeCompensateSkuZsetKey);
        if (!optional.isPresent()) {
            return JsonResult.buildError(ProductErrorCodeEnum.NO_RESULT_ERROR);
        }

        boolean nextPage = false;
        Long count = skuSellerCache.zcard(redisKey);
        if (count.intValue() > (offset + pageSize)) {
            nextPage = true;
        }

        ProductCompensateCollectDTO productCompensateCollectDTO = new ProductCompensateCollectDTO();
        productCompensateCollectDTO.setSkuIdList(optional.get());
        productCompensateCollectDTO.setNextPage(nextPage);
        productCompensateCollectDTO.setTotal(count);
        return JsonResult.buildSuccess(productCompensateCollectDTO);
    }


    /**
     * 根据卖家ID和商品编码判断商品是否可补
     *
     * @param productCompensateRelationQuery
     * @return
     */
    @Override
    public JsonResult<ProductCompensateRelationDTO> checkCompensateSku(ProductCompensateRelationQuery productCompensateRelationQuery) {
        // 参数校验
        checkCompensateSkuParams(productCompensateRelationQuery);

        List<Long> sellerIdList = productCompensateRelationQuery.getSellerIdList();

        // 获取卖家可补商品集合
        Optional<Map<Long, List<String>>> optional = skuSellerCache.queryRedisSortedSetDataMap(sellerIdList,
                AbstractRedisKeyConstants::getSellerTypeCompensateSkuZsetKey);

        if (!optional.isPresent()) {
            return JsonResult.buildSuccess();
        }

        // 构建可补商品和卖家关系,以及不可补商品列表
        ProductCompensateRelationDTO productPurchaseRelationDTO = buildProductCompensateRelation(optional.get(),
                productCompensateRelationQuery.getProductIdList());

        return JsonResult.buildSuccess(productPurchaseRelationDTO);
    }


    /**
     * 构建可补商品和卖家关系,以及不可补商品列表
     *
     * @param skuIdMap
     * @param productIdList
     * @return
     */
    private ProductCompensateRelationDTO buildProductCompensateRelation(Map<Long, List<String>> skuIdMap, Set<String> productIdList) {
        List<String> notCompensateProductId = new ArrayList<>(productIdList.size());
        // 先默认商品都为不可补
        notCompensateProductId.addAll(productIdList);

        Map<Long, List<String>> sellerCompensateProductIds = new HashMap<>(skuIdMap.size());
        for (Map.Entry<Long, List<String>> entry : skuIdMap.entrySet()) {
            List<String> compensateProductIds = entry.getValue();
            List<String> compensateList = new ArrayList<>(compensateProductIds.size());
            for (String sku : compensateProductIds) {
                ProductDetailDO productDetailDO = JsonUtil.json2Object(sku, ProductDetailDO.class);
                if (productIdList.contains(productDetailDO.getSkuId())) {
                    compensateList.add(sku);
                    // 已经可补的商品，在不可补的商品中移除
                    notCompensateProductId.remove(productDetailDO.getSkuId());
                }
            }
            // 当前卖家可补商品
            sellerCompensateProductIds.put(entry.getKey(), compensateList);
        }
        return new ProductCompensateRelationDTO(sellerCompensateProductIds, notCompensateProductId);
    }

    /**
     * 参数校验
     *
     * @param productCompensateRelationQuery
     */
    private void checkCompensateSkuParams(ProductCompensateRelationQuery productCompensateRelationQuery) {
        ParamCheckUtil.checkObjectNonNull(productCompensateRelationQuery);
        ParamCheckUtil.checkCollectionNonEmpty(productCompensateRelationQuery.getProductIdList());
        ParamCheckUtil.checkCollectionNonEmpty(productCompensateRelationQuery.getSellerIdList());
    }

    /**
     * 参数校验
     *
     * @param productCompensateQuery
     */
    private void checkCompensateSkuByPageParams(ProductCompensateQuery productCompensateQuery) {
        ParamCheckUtil.checkObjectNonNull(productCompensateQuery);
        ParamCheckUtil.checkLongNonEmpty(productCompensateQuery.getSellerId());
    }
}
